// Package initialize
// Title  zap.initialize 初始化日志配置
// Description  初始化加载配置参数
// Author  alittlexincan@163.com 2024/07/22 11:36
// update  alittlexincan@163.com 2024/07/22 11:36
package initialize

import (
	"os"
	"path/filepath"
	"time"

	"github.com/spf13/viper"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"xincan.com.cn/tarot-go-framework/global"
)

// InitZapLogger
// Title    			InitZapLogger
// Description   		初始化zap日志配置
// Auth      			alittlexincan@163.com       			时间（2024/07/17 11:36）
// Return    			*viper.Viper, *zap.SugaredLogger     	yaml 解析器实例
func InitZapLogger() (logger *zap.Logger, sugar *zap.SugaredLogger) {

	//获取编码器
	encoder := getEncoder()
	//日志级别
	highPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool { //error级别
		return lev >= zap.ErrorLevel
	})
	lowPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool { //info和debug级别,debug级别是最低的
		return lev < zap.ErrorLevel && lev >= zap.DebugLevel
	})
	//info文件WriteSyncer
	infoFileWriteSyncer := getInfoWriterSyncer()
	//error文件WriteSyncer
	errorFileWriteSyncer := getErrorWriterSyncer()
	//生成core
	//同时输出到控制台 和 指定的日志文件中
	infoFileCore := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(infoFileWriteSyncer, zapcore.AddSync(os.Stdout)), lowPriority)
	errorFileCore := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(errorFileWriteSyncer, zapcore.AddSync(os.Stdout)), highPriority)
	//将info core 和 error 加入core切片
	var coreArr []zapcore.Core
	coreArr = append(coreArr, infoFileCore)
	coreArr = append(coreArr, errorFileCore)
	//生成logger
	logger = zap.New(zapcore.NewTee(coreArr...), zap.AddCaller()) //zap.AddCaller() 显示文件名 和 行号

	global.Logger = logger
	global.Sugar = logger.Sugar()

	return global.Logger, global.Sugar
}

// 彩色日志级别编码器
func colorEncodeLevel(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
	color := getLevelColor(level)
	enc.AppendString(color + level.CapitalString() + "\x1b[0m") // 结尾重置颜色
}

// 根据日志级别返回对应 ANSI 颜色代码
func getLevelColor(level zapcore.Level) string {
	switch level {
	case zapcore.DebugLevel:
		return "\x1b[35m" // 紫色
	case zapcore.InfoLevel:
		return "\x1b[32m" // 绿色
	case zapcore.WarnLevel:
		return "\x1b[33m" // 黄色
	case zapcore.ErrorLevel, zapcore.DPanicLevel, zapcore.PanicLevel, zapcore.FatalLevel:
		return "\x1b[31m" // 红色
	default:
		return "\x1b[0m" // 默认无色
	}
}

// InitZapLogger
// Title    			getEncoder
// Description   		日志编码器
// Auth      			alittlexincan@163.com       			时间（2024/07/17 11:36）
// Update    			alittlexincan@163.com       			时间（2024/07/17 11:36）
// Return    			*viper.Viper, *zap.SugaredLogger     	yaml 解析器实例
func getEncoder() zapcore.Encoder {
	//自定义编码配置
	encoderConfig := zap.NewProductionEncoderConfig()
	encoderConfig.TimeKey = "time" //指定时间字段名
	encoderConfig.LevelKey = "level"
	encoderConfig.NameKey = "logger"
	encoderConfig.CallerKey = "caller"
	encoderConfig.MessageKey = "msg"
	encoderConfig.LineEnding = zapcore.DefaultLineEnding
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder //指定时间格式
	encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder
	encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
	encoderConfig.EncodeLevel = colorEncodeLevel //按级别显示不同颜色，不需要的话取值zapcore.CapitalLevelEncoder就可以了
	return zapcore.NewConsoleEncoder(encoderConfig)
	//return zapcore.NewJSONEncoder(encoderConfig)
}

// getInfoWriterSyncer
// Title    			getInfoWriterSyncer
// Description   		获取info日志文件WriteSyncer
// Auth      			alittlexincan@163.com       			时间（2024/07/17 11:36）
// Update    			alittlexincan@163.com       			时间（2024/07/17 11:36）
// Return    			*zapcore.WriteSyncer     				返回info日志文件WriteSyncer
func getInfoWriterSyncer() zapcore.WriteSyncer {

	strSeparator := string(filepath.Separator)
	stRootDir, _ := os.Getwd()
	stLogFilePath := stRootDir + strSeparator + "logs" + strSeparator + viper.GetString("service.name") + strSeparator + "info-" + time.Now().Format("2006-01-02") + ".log"

	//引入第三方库 Lumberjack 加入日志切割功能
	lumberWriteSyncer := &lumberjack.Logger{
		Filename:   stLogFilePath,                  // 指定日志文件路径
		MaxSize:    viper.GetInt("log.maxSize"),    // 在进行切割之前，日志文件的最大大小（以MB为单位)
		MaxBackups: viper.GetInt("log.maxBackups"), // 日志文件最多保存多少个备份
		MaxAge:     viper.GetInt("log.maxAge"),     // 日志文件最多保存多少天
		Compress:   viper.GetBool("log.compress"),  // Compress确定是否应该使用gzip压缩已旋转的日志文件。默认值是不执行压缩。
	}
	return zapcore.AddSync(lumberWriteSyncer)
}

// getErrorWriterSyncer
// Title    			getErrorWriterSyncer
// Description   		初始化zap日志配置
// Auth      			alittlexincan@163.com       			时间（2024/07/17 11:36）
// Update    			alittlexincan@163.com       			时间（2024/07/17 11:36）
// Return    			*viper.Viper, *zap.SugaredLogger     	yaml 解析器实例
func getErrorWriterSyncer() zapcore.WriteSyncer {

	strSeparator := string(filepath.Separator)
	stRootDir, _ := os.Getwd()
	stLogFilePath := stRootDir + strSeparator + "logs" + strSeparator + viper.GetString("service.name") + strSeparator + "error-" + time.Now().Format("2006-01-02") + ".log"

	//引入第三方库 Lumberjack 加入日志切割功能
	lumberWriteSyncer := &lumberjack.Logger{
		Filename:   stLogFilePath,                  // 指定日志文件路径
		MaxSize:    viper.GetInt("log.maxSize"),    // 在进行切割之前，日志文件的最大大小（以MB为单位)
		MaxBackups: viper.GetInt("log.maxBackups"), // 日志文件最多保存多少个备份
		MaxAge:     viper.GetInt("log.maxAge"),     // 日志文件最多保存多少天
		Compress:   viper.GetBool("log.compress"),  // Compress确定是否应该使用gzip压缩已旋转的日志文件。默认值是不执行压缩。
	}
	return zapcore.AddSync(lumberWriteSyncer)
}
